﻿using Basic.UserModel.WxUser;
using Basic.UserRepository;
using WeDonekRpc.CacheClient.Interface;

namespace Basic.UserCollect.lmpl
{
    internal class WxUserCollect : IWxUserCollect
    {
        private readonly IWxUserRepository _Repository;
        private readonly ICacheController _Cache;

        public WxUserCollect (IWxUserRepository repository, ICacheController cache)
        {
            this._Repository = repository;
            this._Cache = cache;
        }

        public void Bind (WxUserDto user, long userId)
        {
            if (user.IsBind && user.BindUserId == userId)
            {
                return;
            }
            BindWxUser cancel = this.FindBindWxUser(user.ThirdId, userId);
            if (cancel != null && cancel.Id == user.Id)
            {
                return;
            }
            else if (cancel == null)
            {
                this._Repository.Bind(user.Id, userId);
            }
            else
            {
                this._Repository.Bind(user.Id, userId, cancel.Id);
            }
            this._Clear(user, userId);
        }
        public WxUserDto GetUser (long id)
        {
            return this._Repository.Get<WxUserDto>(id);
        }
        public void Cancel (WxUserDto user)
        {
            if (!user.IsBind)
            {
                return;
            }
            this._Repository.CancelBind(user.Id);
            this._Clear(user.ThirdId, user.WxOpenId);
        }

        public WxUserDatum FindUser (long thirdId, string openId)
        {
            string key = string.Join("_", "WxUser", thirdId, openId);
            if (!this._Cache.TryGet(key, out WxUserDatum user))
            {
                user = this._Repository.FindWxUser<WxUserDatum>(thirdId, openId);
                if (user == null)
                {
                    _ = this._Cache.Add<WxUserDatum>(key, null, new TimeSpan(0, 1, 0));
                }
                else
                {
                    _ = this._Cache.Add(key, user);
                }
            }
            return user;
        }
        public long[] FindId (long userId)
        {
            return this._Repository.FindId(userId);
        }
        public void Cancel (long[] ids)
        {
            this._Repository.CancelBind(ids);
        }
        public BindWxUser FindBindWxUser (long thirdId, long userId)
        {
            string key = string.Join("_", "BindWxUser", thirdId, userId);
            if (!this._Cache.TryGet(key, out BindWxUser user))
            {
                user = this._Repository.FindBindWxUser(thirdId, userId);
                if (user == null)
                {
                    _ = this._Cache.Add(key, user, new TimeSpan(0, 1, 0));
                }
                else
                {
                    _ = this._Cache.Add(key, user);
                }
            }
            return user;
        }
        public WxUserDatum WxUserLogin (WxUserBase add)
        {
            WxUserDatum user = this.FindUser(add.ThirdId, add.WxOpenId);
            if (user == null)
            {
                long id = this._Repository.RegWxUser(add);
                this._Clear(add.ThirdId, add.WxOpenId);
                return new WxUserDatum
                {
                    Id = id,
                    IsBind = false,
                };
            }
            return user;
        }

        private void _Clear (long thirdId, string openId)
        {
            string key = string.Join("_", "WxUser", thirdId, openId);
            _ = this._Cache.Remove(key);
        }
        private void _Clear (WxUserDto user, long userId)
        {
            string key = string.Join("_", "BindWxUser", user.ThirdId, userId);
            _ = this._Cache.Remove(key);
            key = string.Join("_", "WxUser", user.ThirdId, user.WxOpenId);
            _ = this._Cache.Remove(key);
        }
    }
}
